#pragma once

#include <glad/glad.h> // 包含glad来获取所有的必须OpenGL头文件
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include "Camera.h"
#include "Material.h"
#include "Light.h"
#include "baseClass/GLog.h"



class Shader
{
private:
    void InitShader(std::string &vertexSrc, std::string &fragmentSrc);
    uint32_t uboCameraMatrices;
    uint32_t uniformBlockCameraIndex;
public:
    // 程序ID
    unsigned int ID;
    // 构造器读取并构建着色器
    Shader(const char* vertexPath, const char* fragmentPath);

    Shader(std::string &vertexSrc, std::string &fragmentSrc);


    
    // 使用/激活程序
    void use(){ glUseProgram(ID);};
    void Unuse(){ glUseProgram(0); };
    void setBool(const std::string &name, bool value) const;  
    void setInt(const std::string &name, int value) const;   
    void setFloat(const std::string &name, float value) const;
    void setMat4(const std::string &name, glm::mat4 value) const;
    void setMat3(const std::string &name, glm::mat3 value) const;

    void SetProjection(glm::mat4 projection){

        glBindBuffer(GL_UNIFORM_BUFFER, uboCameraMatrices);
        glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), glm::value_ptr(projection));
        glBindBuffer(GL_UNIFORM_BUFFER, 0);
    }

    void SetView(glm::mat4 view) {
        
        glBindBuffer(GL_UNIFORM_BUFFER, uboCameraMatrices);
        glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(view));
        glBindBuffer(GL_UNIFORM_BUFFER, 0);
    }

    void InitUboCamera()
    {
        uniformBlockCameraIndex = glGetUniformBlockIndex(ID, "CameraMatrices");
  
        glUniformBlockBinding(ID,  uniformBlockCameraIndex, 0);
        glGenBuffers(1, &uboCameraMatrices);
        glBindBuffer(GL_UNIFORM_BUFFER, uboCameraMatrices);
        glBufferData(GL_UNIFORM_BUFFER, 2 * sizeof(glm::mat4), NULL, GL_STATIC_DRAW);
        glBindBuffer(GL_UNIFORM_BUFFER, 0);
        glBindBufferRange(GL_UNIFORM_BUFFER, 0, uboCameraMatrices, 0, 2 * sizeof(glm::mat4));
    }

    virtual ~Shader(){
        glDeleteProgram(ID);
        ID = 0;
    };
    
};



